[GitHub Actions] GitHub CLIで取得したアイテムのリストをmatrix構文で処理する
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、GitHub Actionsで、GitHub CLIで取得したアイテムのリストをmatrix構文で処理してみました。
matrix構文とは
GitHub Actionsのmatrix構文を使うと、単一のJobの記述で複数パターンの変数要素を指定し、それぞれのパターンに対してJobを実行することができます。
使い方は次のようになります。Jobのstrategy.matrix
で配列形式で変数要素を指定します。
jobs: example_matrix: strategy: matrix: version: [10, 12, 14] os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/setup-node@v3 with: node-version: ${{ matrix.version }}
上記はos
が2要素、version
が3要素であるため、合わせて6パターンのJobが実行されます。
{version: 10, os: ubuntu-latest}
{version: 10, os: windows-latest}
{version: 12, os: ubuntu-latest}
{version: 12, os: windows-latest}
{version: 14, os: ubuntu-latest}
{version: 14, os: windows-latest}
このように、変数要素のパターンを変えながらJobを実行したい場合に、要素ごとにWorkflowの実行やJobの記述を分けたりする必要が無くなってとても便利です。
GitHub CLIで取得したアイテムのリストをmatrixで処理する
matrix構文で指定する変数要素は、Workflow実行内で動的に生成することも可能です。ここではGitHub CLIのgh pr listコマンドで取得したPull Requestのリストを処理してみます。
次のWorkflowでは、1つ目のJobでPull RequestのIssue番号のリストをContextに指定し、2つ目のJobでmatrixに使用しています。このようにJobを2段階にすることによりmarixの要素を動的に生成することができます。
on: push env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: get_pr_matrix: runs-on: ubuntu-latest outputs: matrix: ${{ steps.matrix.outputs.value }} steps: - name: Checkout uses: actions/checkout@v3 - id: matrix run: | pr_list=$(gh pr list --json number --limit 5 | jq '[.[].number]') echo "::set-output name=value::$(echo $pr_list | jq -c .)" do_process: needs: get_pr_matrix runs-on: ubuntu-latest strategy: matrix: value: ${{ fromJson(needs.get_pr_matrix.outputs.matrix) }} steps: - name: Processing for each pull request - run: | echo ${{ matrix.value }}
ポイントとしては、CLIで取得したアイテムをjq
コマンドでJsonパースしてContextに指定する際にコンパクト処理(-c
オプション)をしている所です。
# コンパクト処理をしない場合 $ gh pr list --json number --limit 5 | jq '[.[].number]' [ 1381, 1376, 1373, 1370, 1368 ] # コンパクト処理をした場合 $ pr_list=$(gh pr list --json number --limit 5 | jq '[.[].number]') $ echo $pr_list | jq -c . [1381,1376,1373,1370,1368]
コンパクト処理をしない(改行記号が含まれている)配列はmatrix要素に指定することはできないためです。(また、1回目のjq
実行でコンパクト処理をしていない理由としては、コンパクト処理していない値をGitHub Actions Workflow上ではなぜか変数で上手く扱えなかったためです。)
PushしてWorkflowを実行すると、matrixによりPull Request毎にJobが分けられて処理されています。(13XX
が取得したPull RequestのIssue番号です。)
matrixにより実行されるそれぞれのJob名は<Step名> (matrix要素)
となり、Workflow実行画面上での表示にも使用されるため、それを意識した要素(今回はIssue番号)を使うと良いかと思います。
おまけ:そもそもやりたかったこと
参考までに、matrix構文を使用して元々やりたかったこととしては、Cronで実行して条件に合致するPull Requestを自動でMergeする処理です。この時にGitHub CLIで取得したそれぞれのPull Requestに対して、条件の一致チェックとBase BranchへのMergeを行う必要があったため、matrix構文がとても役に立ちました。
# そもそもやりたかったこと on: schedule: - cron: 0 15 * * * push: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: get_pr_matrix: runs-on: ubuntu-latest outputs: matrix: ${{ steps.matrix.outputs.value }} steps: - name: Checkout uses: actions/checkout@v3 - id: matrix run: | pr_list=$(gh pr list --json number | jq '[.[].number]') echo "::set-output name=value::$(echo $pr_list | jq -c .)" merge_pr: needs: get_pr_matrix runs-on: ubuntu-latest strategy: matrix: value: ${{ fromJson(needs.get_pr_matrix.outputs.matrix) }} steps: - name: Checkout uses: actions/checkout@v3 - name: Set pull request info to Context id: set_pr_info_to_context run: | pull_request=$(gh pr view ${{ matrix.value }} --json title,commits,comments | jq .) echo ${pull_request} | jq . last_comment_body=$(echo ${pull_request} | jq -r '.comments | .[-1].body') echo "LAST_COMMENT_BODY=${last_comment_body}" >> $GITHUB_ENV last_commented_at=$(echo $pull_request | jq -r '.comments | .[-1].createdAt') unixtime_last_commented_at=$(date -d ${last_commented_at} '+%s') echo "UNIXTIME_LAST_COMMENTED_AT=${unixtime_last_commented_at}" >> $GITHUB_ENV last_commit_date=$(echo $pull_request | jq -r '.commits | .[-1].committedDate') unixtime_last_committed_at=$(date -d ${last_commit_date} '+%s') echo "UNIXTIME_LAST_COMMITTED_AT=${unixtime_last_committed_at}" >> $GITHUB_ENV echo "UNIXTIME_THREE_DAYS_AGO=$(date --date "-3 day" '+%s')" >> $GITHUB_ENV - name: Merge Pull Request if: env.LAST_COMMENT_BODY == 'published' && env.UNIXTIME_LAST_COMMITTED_AT < env.UNIXTIME_LAST_COMMENTED_AT && env.UNIXTIME_LAST_COMMENTED_AT < env.UNIXTIME_THREE_DAYS_AGO run: | gh pr merge ${{ matrix.value }} --merge
おわりに
GitHub Actionsで、GitHub CLIで取得したアイテムのリストをmatrix構文で処理してみました。
元々はShellのfor loop
構文を使って行っていた処理が、matrix構文を使うことにより簡略化され、また実行画面上でも処理が可視化できるようになりました。GitHub Actionsの便利なBuilt-in機能なのでどんどん使っていきたいですね!
参考
以上